package Gson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.JSONSerializable;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.*;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Since;
import com.google.gson.internal.Excluder;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.util.*;

/**
 * Created by User on 2017/11/24.
 */
public class APP {

    public static void main(String[] args) throws FileNotFoundException {
        Person person1 = new Person(1L, "阿萨德", 23, Gender.男, new Date(), new Person(2L, "Mary", 21, Gender.女, null));
        Person person2 = new Person(3L, "阿萨德", 23, Gender.男, new Person(4L, "dsa", 21, Gender.女, new Date(), null));
        Person person3 = new Person(5L, "阿萨德", 23, Gender.男, new Person(6L, "asd", 21, Gender.女, null));
        Person person4 = new Person(7L, "阿萨德", 23, Gender.男, new Person(8L, "Madsary", 21, Gender.女, null));
        List list = new ArrayList();
        list.add(person1);
        list.add(person2);
        list.add(person3);
        list.add(person4);


        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.serializeNulls();
        gsonBuilder.setPrettyPrinting();

        Gson gson = gsonBuilder.create();
        gson.fromJson("", Object.class);
        System.out.println(gson.toJson(list));


        Map map = new HashMap();
        map.put("23", null);
        map.put("223", 2);

        // serializeNulls()对空值的对象也进行打印
        System.out.println(new GsonBuilder().serializeNulls().create().toJson(map));
        // {"23":null,"223":2}
        System.out.println(new GsonBuilder().create().toJson(map));
        // {"223":2}

        map.put("2231", 123);

        // setPrettyPrinting()不移除空白  保留json打印格式
        System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(map));
        /**
         {
         "223": 2,
         "2231": 123
         }
         */
        System.out.println(new GsonBuilder().create().toJson(map));
        // {"223":2,"2231":123}

        // 自定义序列化
        System.out.println(new GsonBuilder().registerTypeAdapter(Long.class, new JsonSerializer() {
            @Override
            public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
                // java8 lambda表达式 入参类型必须是接口
                System.out.println(typeOfSrc); // class java.lang.Long
                System.out.println(src); // 2
                System.out.println(context); // com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl@b5c224

                return new JsonPrimitive(String.valueOf(src));
            }
        }).create().toJson(new Person(2L, "Mary", 21, Gender.女, null)));
        // {"id":"2","name":"Mary","age":21,"gender":"女"}
        System.out.println(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));
        // {"id":2,"name":"Mary","age":21,"gender":"女","birthday":"2017-11-27 14:44:23"}
        // excludeFieldsWithoutExposeAnnotation()表示只序列化被com.google.gson.annotations.Expose注解标记的字段
        System.out.println(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));
        // setVersion(1.0)表示当前版本号 @Since(1.1)标记后表示只有在版本号大于等于1.1的情况去序列化
        System.out.println(new GsonBuilder().setVersion(1.0).create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));
        // 默认忽略static和transient修饰的字段    使用excludeFieldsWithModifiers去修改
        System.out.println(new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE | Modifier.TRANSIENT | Modifier.STATIC).create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));

        // 对枚举类的自定义序列化
        System.out.println(new GsonBuilder().registerTypeHierarchyAdapter(Enum.class, new JsonSerializer() {
            @Override
            public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
                System.out.println(src);
                System.out.println(typeOfSrc);
                return new JsonPrimitive(src.toString());
            }
        }).create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));
        // {"id":2,"name":"Mary","age":21,"gender":"woman"}
        // 使用注解@SerializedName("w")标记枚举
        System.out.println(new GsonBuilder().create().toJson(new Person(2L, "Mary", 21, Gender.女, new Date(), null)));
        // {"id":2,"name":"Mary","age":21,"gender":"w"}
    }

    public static class Person {
        private Long id;
        @Expose
        String name;
        @Since(1.1)
        Integer age;
        @Since(1.0)
        Gender gender;
        @Since(1.0)
        transient Date birthday;
        Person wife;

        public Person(Long id, String name, Integer age, Gender gender, Date birthday, Person wife) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.birthday = birthday;
            this.wife = wife;
        }

        public Person(Long id, String name, Integer age, Gender gender, Person wife) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.wife = wife;
        }
    }

    public enum Gender {
        男, 女;

        @Override
        public String toString() {
            if (this.name().equals("男")) return "man";
            if (this.name().equals("女")) return "woman";
            return super.toString();
        }
    }

}
